package com.sun.talk.service.impl

import com.alibaba.fastjson.JSON
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.core.toolkit.IdWorker
import com.sun.talk.base.BaseServiceImpl
import com.sun.talk.entity.FriendsRequest
import com.sun.talk.entity.MyFriends
import com.sun.talk.mapper.UserMapper
import com.sun.talk.entity.User
import com.sun.talk.entity.vo.MyFriendVO
import com.sun.talk.entity.vo.FriendsRequestVO
import com.sun.talk.enums.MsgActionEnum
import com.sun.talk.enums.MsgSignFlagEnum
import com.sun.talk.enums.SearchFriendsStatusEnum
import com.sun.talk.mapper.ChatMsgMapper
import com.sun.talk.mapper.FriendsRequestMapper
import com.sun.talk.mapper.MyFriendsMapper
import com.sun.talk.netty.ChatMsg
import com.sun.talk.netty.DataContent
import com.sun.talk.netty.UserChannelRel
import com.sun.talk.service.UserService
import com.sun.talk.utils.QiNiuUploadUtils
import com.sun.talk.utils.QrCodeUtils
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
import java.util.*
import javax.annotation.Resource

@Service
class UserServiceImpl : BaseServiceImpl<UserMapper, User>(), UserService {
    @Resource
    lateinit var userMapper: UserMapper

    @Resource
    lateinit var myFriendsMapper: MyFriendsMapper

    @Resource
    lateinit var friendsRequestMapper: FriendsRequestMapper

    @Resource
    lateinit var chatMsgMapper: ChatMsgMapper

    /**
     * 判断用户名是否存在
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    override fun queryUserByUsername(username: String): User? {
        return getOne(QueryWrapper<User>().eq("username", username))
    }

    /**
     * 判断用户名是否存在
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    override fun queryUserForLogin(username: String, password: String): User? {
        return getOne(QueryWrapper<User>().allEq(
                mapOf("username" to username, "password" to password)
        ))
    }

    @Transactional(propagation = Propagation.REQUIRED)
    override fun saveUser(user: User): User? {
        val userId = IdWorker.getIdStr()
        val qrCodePath = "/Users/sun/IdeaProjects/TalkServer/src/main/resources/temp/${userId}qrcode.png"
        QrCodeUtils.createQRCode(qrCodePath, "muxin_qrcode:" + user.username)
        val qrCodeUrl = QiNiuUploadUtils.upload(qrCodePath)
        if (qrCodeUrl.isEmpty()) {
            return null
        }
        user.qrcode = qrCodeUrl
        user.id = userId
        return if (save(user)) user else null
    }

    /**
     * 更新用户信息
     */
    @Transactional(propagation = Propagation.REQUIRED)
    override fun updateUserInfo(user: User): User {
        updateById(user)
        return queryUserById(user.id)
    }

    /**
     * 主键查询用户
     */
    @Transactional(propagation = Propagation.REQUIRED)
    override fun queryUserById(userId: String): User {
        return getById(userId)
    }

    /**
     * 搜索好友前置条件
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    override fun preconditionSearchFriends(myUserId: String, friendUserName: String): Int {
        val user = queryUserByUsername(friendUserName) ?: return SearchFriendsStatusEnum.USER_NOT_EXIST.status
        if(user.id == myUserId){
            return SearchFriendsStatusEnum.NOT_YOURSELF.status
        }
        val myFriends = myFriendsMapper.selectOne(QueryWrapper<MyFriends>().allEq(
                mapOf("myUserId" to myUserId, "myFriendUserId" to user.id)
        ))
        if(myFriends != null){
            return SearchFriendsStatusEnum.ALREADY_FRIENDS.status
        }
        return SearchFriendsStatusEnum.SUCCESS.status
    }

    /**
     * 发送添加好友请求
     */
    @Transactional(propagation = Propagation.REQUIRED)
    override fun sendFriendRequest(myUserId: String, friendUserName: String) {
        //查询好友信息
        val friend = queryUserByUsername(friendUserName)!!
        // 查询好友申请记录表
        val friendsRequest = friendsRequestMapper.selectOne(QueryWrapper<FriendsRequest>().allEq(
                mapOf("sendUserId" to myUserId, "acceptUserId" to friend.id)
        ))
        if(friendsRequest == null){
            // 不是你的好友 并且好友申请记录表中没有 则新增
            val request = FriendsRequest(IdWorker.getIdStr(),myUserId,friend.id,Date())
            friendsRequestMapper.insert(request)
        }
    }

    /**
     * 好友请求列表
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    override fun queryFriendRequestList(acceptUserId: String): List<FriendsRequestVO> {
        return userMapper.queryFriendRequestList(acceptUserId)
    }

    /**
     * 删除好友请求
     */
    @Transactional(propagation = Propagation.REQUIRED)
    override fun deleteFriendRequest(sendUserId: String, acceptUserId: String) {
        friendsRequestMapper.delete(QueryWrapper<FriendsRequest>().allEq(
                mapOf("sendUserId" to sendUserId, "acceptUserId" to acceptUserId)
        ))
    }

    /**
     * 通过好友请求
     */
    @Transactional(propagation = Propagation.REQUIRED)
    override fun passFriendRequest(sendUserId: String, acceptUserId: String) {
        //1.保存好友
        saveFriends(acceptUserId,sendUserId)
        //2.逆向保存好友
        saveFriends(sendUserId,acceptUserId)
        //3.删除好友申请记录
        deleteFriendRequest(acceptUserId,sendUserId)

        //使用websocket 通知请求者刷新通讯录
        val sendChannel = UserChannelRel.get(sendUserId)
        if(sendChannel != null) {
            val dataContent = DataContent(MsgActionEnum.PULL_FRIEND.type, ChatMsg())
            sendChannel.writeAndFlush(TextWebSocketFrame(JSON.toJSONString(dataContent)))
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    fun saveFriends(sendUserId: String, acceptUserId: String){
        val myFriends = MyFriends(IdWorker.getIdStr(),sendUserId,acceptUserId)
        myFriendsMapper.insert(myFriends)
    }

    /**
     * 好友列表
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    override fun queryFriendList(userId: String): List<MyFriendVO> {
        return userMapper.queryFriendList(userId)
    }

    /**
     * 保存消息
     */
    @Transactional(propagation = Propagation.REQUIRED)
    override fun saveMsg(chatMsg: ChatMsg): String {
        val msgId = IdWorker.getIdStr()
        val chatMsgDb = com.sun.talk.entity.ChatMsg(msgId,chatMsg.senderId,
                chatMsg.receiverId,chatMsg.msg,MsgSignFlagEnum.UNSIGN.type,Date())
        chatMsgMapper.insert(chatMsgDb)
        return msgId
    }

    /**
     * 批量更新消息签收状态
     */
    @Transactional(propagation = Propagation.REQUIRED)
    override fun updateMsgSigned(msgIds: List<String>) {
        userMapper.batchUpdateMsgSigned(msgIds.joinToString(","))
    }

    /**
     * 获取未签收消息列表
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    override fun queryUnReadMsgList(acceptUserId: String):List<com.sun.talk.entity.ChatMsg>{
        return chatMsgMapper.selectList(QueryWrapper<com.sun.talk.entity.ChatMsg>().allEq(
                mapOf("signFlag" to 0, "acceptUserId" to acceptUserId)
        ))
    }
}